﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bzure.Security.Permissions;
using Bzure.Common.Core;
using Bzure.Common.Data;
using Bzure.Common.Transactions;

namespace Bzure.Apps.Security
{
    public static class RoleExtensions
    {
        /// <summary>
        /// 创建新角色，不允许角色名重复
        /// </summary>
        /// <param name="Public"></param>
        /// <param name="RoleName"></param>
        /// <param name="RoleDescription"></param>
        /// <returns></returns>
        public static TeamRole CreateRole(this Public Public, string RoleName, string RoleDescription)
        {
            if (Actor.Public.GetRoleByName(RoleName).IsNotNullAndEmpty())
            {
                return default(TeamRole);
            }
            TeamRole factor = new TeamRole(Actor.Public .AsUserManager ().GenerateRoleID(), RoleName) { RoleDescription = RoleDescription };
            EntityPostRequest createquest = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Create)
            {
                Entity = factor
            };
            createquest.AppendFieldMap(factor.ID, () => factor.ID);
            createquest.AppendFieldMap(factor.Name, () => factor.Name);
            createquest.AppendFieldMap(factor.RoleDescription, () => factor.RoleDescription);
            Actor.Public.BuildEntityProcessor("SecurityApp").UpdateEntity(createquest);
            return factor;
        }
        /// <summary>
        /// 查询指定角色名的角色
        /// </summary>
        /// <param name="Public"></param>
        /// <param name="RoleName"></param>
        /// <returns></returns>
        public static TeamRole[] GetRoleByName(this Public Public, string RoleName)
        {
            TeamRole factor = new TeamRole(string.Empty, RoleName);
            EntityQueryRequest<TeamRole> query = new EntityQueryRequest<TeamRole>();
            query.AppendConditionMap(factor.Name, () => factor.Name);
            return Actor.Public.BuildEntityProcessor("SecurityApp").QueryEntity(query);
        }
        #region Delete Role
        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="Public"></param>
        /// <param name="RoleID"></param>
        /// <returns></returns>
        public static void DeleteRole(this Public Public, string RoleID, Action<bool> action)
        {
            BizTransaction transaction = BizTransaction.BeginTransaction();

            //step 1 删除角色相应的授权
            RegisterFactor_DeleteDroits(transaction, RoleID);
            //step 2 删除所有用户相应的角色关联
            RegisterFactor_DeleteUserRole(transaction, RoleID);
            //尚未完成
            //step 3 删除角色
            RegisterFactor_DeleteRoles(transaction, RoleID);
            bool ok = transaction.TryCommit();
            if (ok)
            {
                Actor.Public.UpdateLastPermissionChangeTime();
            }
            action(ok);
        }
        static void RegisterFactor_DeleteDroits(BizTransaction transaction, string RoleID)
        {
            IEntityRequestProcess deleteRoleDroitsProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> deleteRoleDroitsFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(deleteRoleDroitsProcessor);
            deleteRoleDroitsFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            deleteRoleDroitsFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {

                EntityPostRequest deleteRoleDroitRequest = BuilddeleteRoleDroitsRequest(RoleID);
                action(deleteRoleDroitsProcessor, deleteRoleDroitRequest);
            };

            transaction.RegisterFactor(deleteRoleDroitsFactor);
        }
        static EntityPostRequest BuilddeleteRoleDroitsRequest(string roleid)
        {
            DroitResource dr = new DroitResource(string.Empty)
            {
                RoleID = roleid
            };

            EntityPostRequest request = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Delete)
            {
                Entity = dr
            };
            request.AppendConditionMap(dr.RoleID, () => dr.RoleID);
            return request;
        }
        static void RegisterFactor_DeleteUserRole(BizTransaction transaction, string RoleID)
        {
            IEntityRequestProcess deleteUserRoleProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> deleteUserRoleFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(deleteUserRoleProcessor);
            deleteUserRoleFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            deleteUserRoleFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {

                EntityPostRequest deleteUserRoleRequest = BuilddeleteUserRoleRequest(RoleID);
                action(deleteUserRoleProcessor, deleteUserRoleRequest);
            };

            transaction.RegisterFactor(deleteUserRoleFactor);
        }
        static EntityPostRequest BuilddeleteUserRoleRequest(string roleid)
        {
            UserRoleMap ur = new UserRoleMap()
            {
                RoleID = roleid
            };

            EntityPostRequest request = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Delete)
            {
                Entity = ur
            };
            request.AppendConditionMap(ur.RoleID, () => ur.RoleID);
            return request;
        }
        static void RegisterFactor_DeleteRoles(BizTransaction transaction, string RoleID)
        {
            IEntityRequestProcess deleteRoleProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> deleteRoleFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(deleteRoleProcessor);
            deleteRoleFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            deleteRoleFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {

                EntityPostRequest deleteRoleRequest = BuilddeleteRoleRequest(RoleID);
                action(deleteRoleProcessor, deleteRoleRequest);
            };

            transaction.RegisterFactor(deleteRoleFactor);
        }
        static EntityPostRequest BuilddeleteRoleRequest(string roleid)
        {
            TeamRole role = new TeamRole(roleid, string.Empty);
            EntityPostRequest request = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Delete)
            {
                Entity = role
            };
            request.AppendConditionMap(role.ID, () => role.ID);
            return request;
        }
        #endregion
        public static TeamRole GetRole(this Public Public, string RoleID)
        {
            TeamRole factor = new TeamRole(RoleID, string.Empty);
            EntityQueryRequest<TeamRole> query = new EntityQueryRequest<TeamRole>();
            query.AppendConditionMap(factor.ID, () => factor.ID);
            return Actor.Public.BuildEntityProcessor("SecurityApp").QueryEntity(query).FirstOrDefault();
        }
    }
}
